package org.tloss.web.editor.form.editors.command;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.DialogCellEditor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.PropertyDescriptor;
import org.eclipse.ui.views.properties.TextPropertyDescriptor;
import org.tloss.web.editor.Utils;
import org.tloss.web.editor.model.Form;
import org.tloss.web.editor.model.Param;
import org.tloss.web.editor.model.Sql;
import org.tloss.web.editor.model.command.LoadEnity;
import org.tloss.web.editor.model.command.ParamVariable;
import org.tloss.web.editor.model.oper.math.ConstOperand;
import org.tloss.web.editor.utils.Constants;
import org.tloss.web.editor.utils.Variable;
import org.tloss.web.editor.utils.VariableBrowser;
import org.tloss.web.editor.utils.VariableProvider;

public class LoadEnityProperty implements IPropertySource {
	public static final String SQLRESOURCE_PRO = "SQLRESOURCE_PRO";
	public static final String NAME_PRO = "NAME_PRO";
	private LoadEnity command;
	private IResourceChangeListener listener;
	private IPropertyDescriptor sqlResource;
	private IPropertyDescriptor name;
	private Form form;

	private IPropertyDescriptor[] descriptors;

	public Form getForm() {
		return form;
	}

	public LoadEnityProperty() {
		descriptors = new IPropertyDescriptor[2];
		name = new TextPropertyDescriptor(NAME_PRO, "Name");
		descriptors[0] = name;
		sqlResource = new PropertyDescriptor(SQLRESOURCE_PRO, "Sql Resource") {
			@Override
			public CellEditor createPropertyEditor(Composite parent) {
				DialogCellEditor cellEditor = new DialogCellEditor(parent) {

					@Override
					protected Object openDialogBox(Control cellEditorWindow) {
						IProject project = Utils.getCurrentProject();
						if (project != null) {
							IResource container = project
									.findMember(Constants.SQL_FOLDER);
							if (container != null
									&& container.getType() == IResource.FOLDER) {
								FilteredResourcesSelectionDialog dialog = new FilteredResourcesSelectionDialog(
										cellEditorWindow.getShell(), false,
										(IFolder) container, IResource.FILE);
								dialog.open();
								if (dialog.getReturnCode() == Window.OK) {
									Object object = dialog.getFirstResult();
									if (object != null) {
										IFile file = (IFile) object;
										return file.getFullPath().toString();
									}
								}
							}
						}
						return "";
					}
				};
				return cellEditor;
			}
		};
		descriptors[1] = sqlResource;
	}

	public LoadEnity getCommand() {
		return command;
	}

	public void setForm(Form form) {
		this.form = form;
	}

	public void setCommand(LoadEnity command) {
		this.command = command;
	}

	public IResourceChangeListener getListener() {
		return listener;
	}

	public void setListener(IResourceChangeListener listener) {
		this.listener = listener;
	}

	@Override
	public Object getEditableValue() {
		return this;
	}

	@Override
	public IPropertyDescriptor[] getPropertyDescriptors() {
		return descriptors;
	}

	@Override
	public Object getPropertyValue(Object arg0) {
		if (SQLRESOURCE_PRO.equals(arg0)) {
			return command.getSqlResource() != null ? command.getSqlResource()
					: "";
		}
		if (NAME_PRO.equals(arg0)) {
			return command.getVariableName() != null ? command
					.getVariableName() : "";
		}
		Sql sql = command.getSql();
		if (sql != null) {
			List<Param> params = sql.getParams();
			List<ParamVariable> paramVariables = command.getParamVariables();
			if (paramVariables == null
					|| (params != null && paramVariables.size() != params
							.size())) {
				paramVariables = new ArrayList<ParamVariable>();
				command.setParamVariables(paramVariables);
				if (params != null && params.size() > 0) {
					for (int i = 0; i < params.size(); i++) {
						paramVariables.add(new ParamVariable());
						String value = params.get(i).getValue();
						value = (value == null ? "" : value);
						ConstOperand constOperand = new ConstOperand();
						constOperand.setValue(value);
						paramVariables.get(i).setOperand(constOperand);
					}
				}
			}

			if (params != null && params.size() > 0) {
				for (int i = 0; i < params.size(); i++) {
					if (("PARAM_" + i).equals(arg0)) {
						return paramVariables.get(i).getOperand() != null ? paramVariables
								.get(i).getOperand() : "";
					}
				}
			}
		}
		return "";
	}

	@Override
	public boolean isPropertySet(Object arg0) {

		return false;
	}

	@Override
	public void resetPropertyValue(Object arg0) {

	}

	public List<Object> getOperandList() {
		if (listener instanceof VariableProvider) {
			return ((VariableProvider) listener).getCurrentCommandVariables();
		}
		return Collections.emptyList();
	}

	@Override
	public void setPropertyValue(Object arg0, Object arg1) {
		if (SQLRESOURCE_PRO.equals(arg0)) {
			command.setSqlResource(arg1.toString());
			try {
				Sql sql = Utils.loadSql(arg1.toString());
				if (sql != null) {
					command.setSql(sql);
					List<Param> params = sql.getParams();
					if (params != null && params.size() > 0) {
						descriptors = new IPropertyDescriptor[params.size() + 2];
						descriptors[0] = name;
						descriptors[1] = sqlResource;
						for (int i = 0; i < params.size(); i++) {
							Utils.logInfo("PARAM_" + i+": "+params.get(i).getName());
							PropertyDescriptor descriptor = new PropertyDescriptor(
									"PARAM_" + i, params.get(i).getName()) {
								public CellEditor createPropertyEditor(
										Composite parent) {
									DialogCellEditor cellEditor = new DialogCellEditor(
											parent) {
										@Override
										protected Object openDialogBox(
												Control arg0) {
											VariableBrowser dialog = new VariableBrowser(
													arg0.getShell());
											dialog.setSupportedVariable(getOperandList());
											if (dialog.open() == Window.OK) {
												List<Variable> variables = dialog
														.getVariable();
												if (variables.size() > 0)
													return variables.get(0);
											}
											return null;
										}
									};
									return cellEditor;
								};
							};
							descriptor.setCategory("Param");
							descriptors[i + 2] = descriptor;
						}
					}
				}
			} catch (Exception e) {
				Utils.logError("Error to load sql resource", e);
			}

		} else if (NAME_PRO.equals(arg0)) {
			command.setVariableName(arg1.toString());
		} else {
			Sql sql = command.getSql();
			if (sql != null) {
				List<Param> params = sql.getParams();
				List<ParamVariable> paramVariables = command
						.getParamVariables();
				if (paramVariables == null) {
					paramVariables = new ArrayList<ParamVariable>();
					command.setParamVariables(paramVariables);
					if (params != null && params.size() > 0) {
						paramVariables.add(new ParamVariable());
					}
				}
				boolean found = false;
				if (params != null && params.size() > 0) {
					for (int i = 0; !found && i < params.size(); i++) {
						if (("PARAM_" + i).equals(arg0)) {
							if (arg1 != null) {
								Variable variable = (Variable) arg1;
								paramVariables.get(i).setParamName(
										params.get(i).getName());
								paramVariables.get(i).setOperand(
										variable.convertToMathOperand());

							}
							found = true;
						}
					}
				}
			}
		}
		if (listener != null) {
			listener.resourceChanged(null);
		}
	}
}
